package com.macaline.util;

import net.sf.json.JSONObject;
import org.apache.commons.codec.binary.Base64;
import org.junit.jupiter.api.Test;

import java.io.ByteArrayInputStream;
import java.io.InputStreamReader;
import java.io.StringWriter;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Map;
import java.util.TreeMap;

/**
 * 加密解密工具
 */
public class SHA1Util {


    private final static String SIGN_TYPE_RSA = "RSA";
    private final static String SIGN_ALGORITHMS = "SHA1WithRSA";
    private final static String CHARSETTING = "UTF-8";

    /**
     * 获取私钥PKCS8格式（需base64）
     * @param algorithm
     * @param priKey
     * @return PrivateKey
     * @throws Exception
     */
    public static PrivateKey getPrivateKeyFromPKCS8(String algorithm, String priKey) throws Exception {
        if (algorithm == null || "".equals(algorithm) || priKey == null || "".equals(priKey))
            return null;

        KeyFactory keyFactory = KeyFactory.getInstance(algorithm);

        byte[] encodedKey = StreamUtil.readText(new ByteArrayInputStream(priKey.getBytes())).getBytes();
        encodedKey = Base64.decodeBase64(priKey.getBytes());

        return keyFactory.generatePrivate(new PKCS8EncodedKeySpec(encodedKey));
    }

    /**
     * 通过证书获取公钥（需BASE64，X509为通用证书标准）
     * @param algorithm
     * @param pubKey
     * @return PublicKey
     * @throws Exception
     */
    public static PublicKey getPublicKeyFromX509(String algorithm, String pubKey) throws Exception {

        if (algorithm == null || "".equals(algorithm) || pubKey == null || "".equals(pubKey))
            return null;

        KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
        StringWriter writer = new StringWriter();
        StreamUtil.io(new InputStreamReader(new ByteArrayInputStream(pubKey.getBytes())), writer);

        byte[] encodeByte = writer.toString().getBytes();
        encodeByte = Base64.decodeBase64(pubKey.getBytes());

        return keyFactory.generatePublic(new X509EncodedKeySpec(encodeByte));
    }

    /**
     * 使用私钥对字符进行签名
     * @param plain  内容体
     * @param prikey  私钥
     * @return String
     * @throws Exception
     */
    public static String sign(String plain, String prikey) throws Exception {
        if (plain == null || "".equals(plain) || prikey == null || "".equals(prikey))
            return null;

        PrivateKey privatekey = getPrivateKeyFromPKCS8(SIGN_TYPE_RSA, prikey);
        Signature signature = Signature.getInstance(SIGN_ALGORITHMS);
        signature.initSign(privatekey);
        signature.update(plain.getBytes(CHARSETTING));
        byte[] signed = signature.sign();

        return new String(Base64.encodeBase64(signed));
    }

    /**
     * 将内容体、签名信息、及对方公钥进行验签
     * @param plain  内容体
     * @param sign   签名信息
     * @param pubkey  对方公钥
     * @return boolean
     * @throws Exception
     */
    public static boolean virefy(String plain, String sign, String pubkey) throws Exception {
        if (plain == null || "".equals(plain) || sign == null || "".equals(sign) || pubkey == null || "".equals(pubkey))
            return false;

        PublicKey publicKey = getPublicKeyFromX509(SIGN_TYPE_RSA, pubkey);
        Signature signature = Signature.getInstance(SIGN_ALGORITHMS);
        signature.initVerify(publicKey);
        signature.update(plain.getBytes(CHARSETTING));

        return signature.verify(Base64.decodeBase64(sign.getBytes()));
    }


    /**
     * 测试
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {
        //**  私钥密钥此处简单演示，应做成可配置    **/
        String privateKey = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDQkEK4hB53EHxICoXmMWW+sB/xmM4QqTbplamxsTPhlClh93PZ/z7T2S6bOnzhI4mgxTfmCOekUsQ82cw0eW6ou9ge7kK960ECsoz70nrqVz4lHMFdRz23W/cTY9vUu6pBV2Qk2j3n3M6kG+evCPPIrgPiC1QXGwXsagNP2q3n1jNxT5AyxLfp+CF9vpVMoBuiR52TBOPJ6zidG+ktNAo2WKE43Ym8EkM7/7/zb4jF7lDrPxLW/4LpxRqsrAl9iZtQa52YRuX6hHaCa+LUe4cGtH2CqYYodVb9F5XWdMxViupQQauHjY/Ypq5ZWB2CHXwC2B5fqR1dE7wlruY6ohlVAgMBAAECggEBAItFOfii6QES9hrZRA6yP8H1NG+NXVVM2cljUlzA+ucQnA26Qxd4VYj7xx6LEOb6ZyX/bFNk8OIPDtGfkrgbuqRcQ3ZsHg9acCAQAQsLw16HAY2gxRK3xuOROs0s6pgE9S0K4Wmmfp49GZQGulBsxvXkFd21OOLw/aSgKjQB0A02DJA9ij9hiWroQUNRNeS6bqnTvf21u/pEa+quq7JSNGw/XqlR/T/racKZVUdOcXRjBItSddYa1qP/0qr+Vs965AodjCk3uMQ9TPZQZlRBOT7pvWaDJ7wyuV9cn01RfqYrAas+z8sY7uynGYqfSEmdVOWbnjmt13y/WdUBnD9e5GECgYEA7VCxQrp7UkPPwzZnviOZ5KWqzvMIAHTRKl6t0MHrYFBJMopKEOtZ6Ixyj8Ft1Q2i83gML60Nyx14MPwzW814n597PQi3jBT2wJNd15glerofutPiL8jucSChkHNS+1hb3stf9d/TKrOLBhjp2FfX3iFJj6HNYPZdh/ASjP9fNvkCgYEA4PwNJUJyigOUQ8s0vcvdtZETRq/si7o6mK0aTty4u8jNJOnOZHz42tQ5AY7QSQXFUd2ZSQbsjF7zEETlQvYSQt7DE1ijTfarWxElDYTi+FJX1whGkpN7MHe2Oq2ii3qmYq8PnKR3MBi2X+MEoBNlYiZ2lKdoJqPNDie0FEsCAD0CgYEAzTmiAYXJDexMqJHNB3Y8KKpH2236doKPO+fiwoxgo8rqcgV7ZcRR3TRQAheRhtSjHY+sYjJyojta7Gm9dF9tOAUwCykVqdObTBBk8APILaj1tZh0m0RVR4mjjorcsTXJRRN1aejk8aGQ0XYMDCZzLMp2lfqj5H1JhzxKnppdWekCgYAwIFqjhMJBmaBmnBpNG0Xy5/Sqo0lDXnPYYvcEtZxitwKDCeyXfFAzZ0BGgAk4BZ7+8xsuDugc4ta1vTcZis+/NC2gfs54B/MByPoXGT0AB4U4v1FxW1D3vjPh+3CQy4y6AV6ikF/ajv68JjDAGUYPp9Cn3eOemF1t0LppuN3VtQKBgDEyN/DlcAHPAkqgDthVHNWEfgm1c4CsHMGTGQUprFlSCH7y6Lmx4B0p14xmdDbz0D6X3ccXb29xtrlDKS5XDGJgY7Yo4w74BM+rcFUYCcnhpbdvJbyEkfOWSXUBu8xJ3bE32Jq7mNut1Ld3QgYh0ykEoF5Lb/C9Nk6G4ISyliD0";
        String publicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0JBCuIQedxB8SAqF5jFlvrAf8ZjOEKk26ZWpsbEz4ZQpYfdz2f8+09kumzp84SOJoMU35gjnpFLEPNnMNHluqLvYHu5CvetBArKM+9J66lc+JRzBXUc9t1v3E2Pb1LuqQVdkJNo959zOpBvnrwjzyK4D4gtUFxsF7GoDT9qt59YzcU+QMsS36fghfb6VTKAbokedkwTjyes4nRvpLTQKNlihON2JvBJDO/+/82+Ixe5Q6z8S1v+C6cUarKwJfYmbUGudmEbl+oR2gmvi1HuHBrR9gqmGKHVW/ReV1nTMVYrqUEGrh42P2KauWVgdgh18AtgeX6kdXRO8Ja7mOqIZVQIDAQAB";
        String plain = "plain：\"PLAIN\":{\"BODY\":{\"returnCode\":\"AAAAAAA\",\"status\":\"00\",\"returnMsg\":\"交易成功\",\"mobileNo\":\"15555524587\"},\"HEAD\":{\"spdbJnlNo\":\"997907074816\",\"timeStamp\":\"1435152316796\",\"transId\":\"MiguRepay\",\"jnlNo\":\"Y000Y021120140605\",\"version\":\"1.0\"}}";
        System.out.println(plain);
        String sign = sign(plain, privateKey);
        //签名信息
        System.out.println("length:" + sign.length());
        System.out.println(sign);

        //签名信息
        //String sign = "BYyaHBgXhAZcjW0VUW1Cx7IpACMCkdmLkF5WkkgVEJboNtDzbQ0hRJ6v6xYDCrHKwTTigq9VpVKnyWAdvYkXlQyTs5vK0wx9aPlLaPFj6e8PZfd3+GM+Azwt15vgoaLs6GxcAZJ7FQMVkRqZWRv1MNorMh0rPLNwbdZgVF3m1+g=";

        //验签结果（接收方使用对方公钥验签）
        System.out.println(virefy(plain, sign, publicKey));

        //组装报文BODY内的内容
        Map<String, String> dataMap = new TreeMap();
        dataMap.put("param1", "value1");
        dataMap.put("param2", "value2");
        dataMap.put("param3", "value3");
        //生成最终报文（Json）
        String body = JSONObject.fromObject(dataMap).toString();
        System.out.println(body);
    }

}
